#include "main.h"
#include "nucCommu.h"
#include "bsp_nucCom.h"
#include "robot_total_mode.h"
#include "struct_typedef.h"
#include "detect_task.h"
#include "OLED.h"
#include "cmsis_os.h"
#include "string.h"
#include "bsp_usart.h"
#include "naive_gimbal_task.h"
#include "debugConfig.h"

#include "referee.h"    // new

extern UART_HandleTypeDef huart1;
extern DMA_HandleTypeDef hdma_usart1_rx;

#define NUC_DATA_AVAILABLE 1
#define NUC_DATA_NOT_AVAILABLE 0


uint32_t upgimbalreadmark = NUC_DATA_NOT_AVAILABLE;  //����ʹ�ñ�־��ֵΪ��������ݲ����ã���ʹ�ù�����ֵΪһ�������ݿ��ã������պ���δ��ʹ�ã�
uint32_t upshootreadmark = NUC_DATA_NOT_AVAILABLE;
uint32_t downgimbalreadmark = NUC_DATA_NOT_AVAILABLE;  //����ʹ�ñ�־��ֵΪ��������ݲ����ã���ʹ�ù�����ֵΪһ�������ݿ��ã������պ���δ��ʹ�ã�
uint32_t downshootreadmark = NUC_DATA_NOT_AVAILABLE;

static void sbus_to_nucCtrl(volatile const uint8_t *sbus_buf, toSTM32_t *nuc_info);
//nuc control data 
//nuc���Ʊ���
toSTM32_t nuc_ctrl;

//receive data, 44 bytes one frame, but set 88 bytes 
//����ԭʼ���ݣ�Ϊ44���ֽڣ�����88���ֽڳ��ȣ���ֹDMA����Խ��
static uint8_t nucinfo_rx_buf[2][NUCINFO_RX_BUF_NUM];
// �ṩ�߲�η�װ������ֱ�����ýϵͲ��ͷ�ļ�
void nuc_control_init(void)
{
    NUC_com_init(nucinfo_rx_buf[0], nucinfo_rx_buf[1], NUCINFO_RX_BUF_NUM);
}

//У�����֤
uint32_t CheckSum(toSTM32_t* data)
{
    uint32_t verification = 0;
	uint32_t *p;
	p = (uint32_t*)(data);
	int i;
    for(i=1;i<9;i++)
    {
        verification += ~p[i];
    }
    return verification;
}

/**
  * @brief          ��ȡnuc����ָ��
  * @param[in]      none
  * @retval         nuc����ָ��
  */

// �ṩʵʱ���µ�NUC�����Ӧ������ָ��
const toSTM32_t *get_nuc_control_point(void)
{
    return (const toSTM32_t*)&nuc_ctrl;
}



//������ݵĽ���״̬
//��̨
void upgimbalSetReadMark(void)
{
    upgimbalreadmark = NUC_DATA_AVAILABLE;   //���ݸոձ����գ���δʹ��
}

void upgimbalClearReadMark(void)
{
    upgimbalreadmark = NUC_DATA_NOT_AVAILABLE;
}

void downgimbalSetReadMark(void)
{
    downgimbalreadmark = NUC_DATA_AVAILABLE;   //���ݸոձ����գ���δʹ��
}

void downgimbalClearReadMark(void)
{
    downgimbalreadmark = NUC_DATA_NOT_AVAILABLE;
}

int gimbal_NUC_is_available(void)
{
    return (upgimbalreadmark == NUC_DATA_AVAILABLE);
    return (downgimbalreadmark == NUC_DATA_AVAILABLE);
}
//����
void upshootSetReadMark(void)
{
    upshootreadmark = NUC_DATA_AVAILABLE;   //���ݸոձ����գ���δʹ��
}
 
void upshootClearReadMark(void)
{
    upshootreadmark = NUC_DATA_NOT_AVAILABLE;
}

void downshootSetReadMark(void)
{
    downshootreadmark = NUC_DATA_AVAILABLE;   //���ݸոձ����գ���δʹ��
}
 
void downshootClearReadMark(void)
{
    downshootreadmark = NUC_DATA_NOT_AVAILABLE;
}

int shoot_NUC_is_available(void)
{
    return (upshootreadmark == NUC_DATA_AVAILABLE);
    return (downshootreadmark == NUC_DATA_AVAILABLE);
}

// ����NUC�����Ƿ������
static int verifiy_pass(void)
{
    int8_t i;
    uint8_t sum = 0;
    uint8_t * data = (uint8_t *) &nuc_ctrl;
    for(i=1;i<sizeof(toSTM32_t)-2;i++)
        sum += data[i];
    if(nuc_ctrl.checksum == sum)
        return 1;
    else
        return 0;
}

//�����ж�
void USART1_IRQHandler(void)
{
    if(huart1.Instance->SR & UART_FLAG_RXNE)//���յ�����//�����ж�
    {
        __HAL_UART_CLEAR_PEFLAG(&huart1);
    }
    else if(USART1->SR & UART_FLAG_IDLE)//�����ж�
    {
        static uint16_t this_time_rx_len = 0;

        __HAL_UART_CLEAR_PEFLAG(&huart1);

        if ((hdma_usart1_rx.Instance->CR & DMA_SxCR_CT) == RESET)
        {
            /* Current memory buffer used is Memory 0 */
    
            //disable DMA
            //ʧЧDMA
            __HAL_DMA_DISABLE(&hdma_usart1_rx);

            //get receive data length, length = set_data_length - remain_length
            //��ȡ�������ݳ���,���� = �趨���� - ʣ�೤��
            this_time_rx_len = NUCINFO_RX_BUF_NUM- hdma_usart1_rx.Instance->NDTR;

            //reset set_data_lenght
            //�����趨���ݳ���
            hdma_usart1_rx.Instance->NDTR = NUCINFO_RX_BUF_NUM;

            //set memory buffer 1
            //�趨����??1
            hdma_usart1_rx.Instance->CR |= DMA_SxCR_CT;
            
            //enable DMA
            //ʹ��DMA
            __HAL_DMA_ENABLE(&hdma_usart1_rx);

            if(this_time_rx_len == NUCINFO_FRAME_LENGTH)
            {   
                sbus_to_nucCtrl(nucinfo_rx_buf[0], &nuc_ctrl);
                if(verifiy_pass())
                {
                    detect_hook(MINI_PC_TOE);
                    upgimbalSetReadMark();
                    upshootSetReadMark();
                    downgimbalSetReadMark();
                    downshootSetReadMark();
                }
            }
        }
        else
        {
            /* Current memory buffer used is Memory 1 */
            //disable DMA
            //ʧЧDMA
            __HAL_DMA_DISABLE(&hdma_usart1_rx);

            //get receive data length, length = set_data_length - remain_length
            //��ȡ�������ݳ���,���� = �趨���� - ʣ�೤��
            this_time_rx_len = NUCINFO_RX_BUF_NUM - hdma_usart1_rx.Instance->NDTR;

            //reset set_data_lenght
            //�����趨���ݳ���
            hdma_usart1_rx.Instance->NDTR = NUCINFO_RX_BUF_NUM;

            //set memory buffer 0
            //�趨����??0
            DMA2_Stream5->CR &= ~(DMA_SxCR_CT);
            
            //enable DMA
            //ʹ��DMA
            __HAL_DMA_ENABLE(&hdma_usart1_rx);

            if(this_time_rx_len == NUCINFO_FRAME_LENGTH)
            {   
                //����nuc��������
                sbus_to_nucCtrl(nucinfo_rx_buf[1], &nuc_ctrl);
                if(verifiy_pass())
                {
                    detect_hook(MINI_PC_TOE);
                    upgimbalSetReadMark();
                    upshootSetReadMark();
                    downgimbalSetReadMark();
                    downshootSetReadMark();
                }
            }
        }
    }
}

/**
  * @brief          nuc����Э�����
  * @param[in]      sbus_buf: ԭ������ָ��
  * @param[out]     rc_ctrl: nuc����ָ��
  * @retval         none
  */

//���ݽ����������ԵĴ��ݹ������Ƿ�Ϊ��ȷ�ģ������Ƿ�ᷴ����??

static void sbus_to_nucCtrl(volatile const uint8_t *sbus_buf, toSTM32_t *nuc_ctrl)
{
    if (sbus_buf == NULL || nuc_ctrl == NULL)
    {
        return;
    }
    (*nuc_ctrl)=(*((toSTM32_t*)sbus_buf));
}

//�ҵ��˷���1��δ�ҵ��򷵻�0.�����͵�found�ֶ�Ϊ1��Ϊ�ҵ�
int foundArmor(void)
{
    #ifndef TEST_USART
    if(toe_is_error(MINI_PC_TOE))
        return 0;
    if(nuc_ctrl.found_armor == 1)
        return 1;
    else
        return 0;
    #endif
}


/**
  * @brief          send nuc data by usart1
  * @param[in]      data: toNUC data, 32 bytes
  * @retval         none
  */
/**
  * @brief          ͨ��usart1����sbus����,��usart3_IRQHandle����
  * @param[in]      data: sbus����, 32�ֽ�
  * @retval         none
  */
void send_to_nuc(toNUC_t * data)
{
    static uint8_t usart_tx_buf[sizeof(toNUC_t)];
    memcpy(usart_tx_buf, (uint8_t*)data, sizeof(toNUC_t));
    usart1_tx_dma_enable(usart_tx_buf, sizeof(toNUC_t));
}

toNUC_t toNUCData={0,0,0,0,0,0,0,0,0,0};

void to_nuc_send_task(void const *pvParameters)
{
    osDelay(1000);
    while(1)
    {
        // new
        #ifdef TEST_USART
        if(verifiy_pass()){
            toNUCData=nuc_ctrl;
        }
        #else
        get_toNUCData(&toNUCData);
        #endif
        send_to_nuc(&toNUCData);
        osDelay(100);
    }
}

#ifdef SHOW_UART_TO_NUC
static int calc_sum(void)
{
    int8_t i;
    uint8_t sum = 0;
    uint8_t * data = (uint8_t *) &nuc_ctrl;
    for(i=1;i<sizeof(toSTM32_t)-2;i++)
        sum += data[i];
    return sum;
}


void OLED_USART(void){
    //OLED_printf(0,0,"p:%d y:%d x:%d y:%d w:%d shoot:%d check:%d",nuc_ctrl.pitch,nuc_ctrl.yaw,nuc_ctrl.x,nuc_ctrl.y,nuc_ctrl.w,nuc_ctrl.shoot,calc_sum());
}
#endif


